from rest_framework import serializers
from . import models
from rest_framework_jwt.settings import api_settings
from rest_framework.exceptions import ValidationError

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER


class UserModelSerializer(serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = models.User
        fields = ['username', 'password']
        extra_kwargs = {
            'username': {'write_only': True},
            'password': {'write_only': True},
        }

    # 全局钩子(校验用户名密码是否正确，登陆成功签发token)
    def validate(self, attrs):
        # 取出用户名密码
        username = attrs.get('username')
        password = attrs.get('password')
        import re
        if re.match('^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(mobile=username).first()
        elif re.match('^.+@>+$', username):
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()
        # 校验user，校验密码
        if user and user.check_password(password):
            # 签发token
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            self.context['token'] = token
            self.context['user'] = user
            return attrs
        else:
            raise ValidationError('用户名或密码错误')


from django.core.cache import cache
from django.conf import settings

class UserPhoneMOdelSerializer(serializers.ModelSerializer):
    code = serializers.CharField()  # 要重写code
    mobile = serializers.CharField(max_length=11)
    class Meta:
        model = models.User
        fields = ['mobile', 'code']
    # 全局钩子(校验手机号和验证码，正确则登录成功，签发token)
    def validate(self, attrs):
        mobile = attrs.get('mobile')
        code = attrs.get('code')
        # 从缓存中取出这个手机号对应的验证码
        cache_code = cache.get(settings.SMS_PHONE_CACHE % mobile)
        if cache_code and cache_code == code:
            # 可以登录，根据手机号查到用户，给这个用户签发token
            user = models.User.objects.get(mobile=mobile)
            # 签发token
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            self.context['token'] = token
            self.context['user'] = user
            return attrs
        else:
            raise ValidationError('验证码错误')

class UserRegisterModelSerializer(serializers.ModelSerializer):
    code = serializers.CharField(write_only=True)
    class Meta:
        model = models.User
        fields = ['mobile', 'code', 'password']
    # 给手机号和password加局部钩子
    def validate_mobile(self, data):
        import re
        if re.match('^1[3-9][0-9]{9}$', data):
            return data
        else:
            raise ValidationError('手机号不合法')
    # 全局钩子
    def validate(self, attrs):
        mobile = attrs.get('mobile')
        code = attrs.get('code')
        # 检验code是否是我们给的，从缓存中取出手机号对应的验证码
        cache_code = cache.get(settings.SMS_PHONE_CACHE % mobile)
        if cache_code and cache_code == code:
            # 可以注册
            # 重写create(因为密码是密文)，使用create_user创建用户
            attrs.pop('code')
            # 加入username
            attrs['username'] = mobile
            return attrs
        else:
            # 不可注册
            raise ValidationError('验证码错误')

    def create(self, validated_data):
        user = models.User.objects.create_user(**validated_data)
        return user
